﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;

namespace StyleMVVM.DependencyInjection.Impl
{
	public class CachedLifeCycleContainer : ILifeCycleContainer
	{
		private readonly bool slidingWindow;
		private readonly TimeSpan timeOut;
		private readonly string cacheKey;

		public CachedLifeCycleContainer(bool slidingWindow, TimeSpan timeOut)
		{
			this.slidingWindow = slidingWindow;
			this.timeOut = timeOut;

			cacheKey = Guid.NewGuid().ToString();
		}

		public object RetrieveObject(IExportStrategy strategy,
		                             ExportLifeCycleMethod exportMethod,
		                             IDependencyInjectionContainer container,
		                             IInjectionContext injectionContext,
		                             [ReadOnlyArray] object[] constructorParams)
		{
			object returnValue = MemoryCache.Default.Get(cacheKey);

			if (returnValue == null)
			{
				if (constructorParams == null || constructorParams.Length > 0)
				{
					constructorParams = new object[0];
				}

				IDisposalScope oldScope = injectionContext.DisposalScope;

				// we need to null out the disposal scope because it's not allowed for cached types
				injectionContext.DisposalScope = null;

				returnValue = exportMethod(injectionContext, constructorParams);

				injectionContext.DisposalScope = oldScope;

				if (returnValue != null)
				{
					if (slidingWindow)
					{
						MemoryCache.Default.Add(cacheKey,
						                        returnValue,
						                        new CacheItemPolicy
							                        {
								                        SlidingExpiration = timeOut
							                        });
					}
					else
					{
						MemoryCache.Default.Add(cacheKey,
						                        returnValue,
						                        new CacheItemPolicy
							                        {
								                        AbsoluteExpiration = DateTime.Now.Add(timeOut)
							                        });
					}
				}
			}

			return returnValue;
		}

		public void Shutdown()
		{
			
		}
	}
}